Limitation Systeme

https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html

cgroups in userspace

tested on ubuntu 20.04

setup and test config

install cgroup-tools (may be called libcgroup on other distributions)

apt-get install cgroup-tools

fetch cgred.conf from sample configuration

cp /usr/share/doc/cgroup-tools/examples/cgred.conf /etc/

create cgconfig.conf

vim /etc/cgconfig.conf

with the following content:

group chromium {
     # limit cpu to 2 cores : 2*100 percent *1000
     cpu {
         cpu.cfs_quota_us=200000;
     }
     # limit memory to 1 GB
     memory {
         memory.limit_in_bytes = 1024m;
     }
}

create cgrules.conf

vim /etc/cgrules.conf

with the following content:

#<user>                   <controllers>       <destination>
#<user>:<process name>    <controllers>       <destination>
dealingtrap:/snap/bin/chromium   cpu,memory        chromium

test the configuration by parsing the setting and launching the daemon

/usr/sbin/cgconfigparser -l /etc/cgconfig.conf
/usr/sbin/cgrulesengd -vvv

confirm that no task are currently managed by the new cgroup chromium

cat /sys/fs/cgroup/cpu/chromium/tasks

restart chromium in userspace and check that the new process is managed by the new cgroup

cat /sys/fs/cgroup/cpu/chromium/tasks

setup services to enable userspace cgroups at launch

create cgconfigparser.service

vim /etc/systemd/system/cgconfigparser.service

with the following content:

[Unit]
Description=cgroup config parser
After=network.target

[Service]
User=root
Group=root
ExecStart=/usr/sbin/cgconfigparser -l /etc/cgconfig.conf
Type=oneshot

[Install]
WantedBy=multi-user.target

create cgrulesgend.service

vim /etc/systemd/system/cgrulesgend.service

with the following content:

[Unit]
Description=cgroup rules generator
After=network.target cgconfigparser.service

[Service]
User=root
Group=root
Type=forking
EnvironmentFile=-/etc/cgred.conf
ExecStart=/usr/sbin/cgrulesengd
Restart=on-failure

[Install]
WantedBy=multi-user.target

And activate the new systemd services

systemctl daemon-reload
systemctl enable cgconfigparser
systemctl enable cgrulesgend
systemctl start cgconfigparser
systemctl start cgrulesgend

enable swap usage control in cgroup (on ubuntu)

On ubuntu the kernel requires some flag being enabled to allow swap control per process.

Edit kernel options in grub configuration:

sudoedit /etc/default/grub

add the fllowing options to GRUB_CMDLINE_LINUX:

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"

save the config and update grub:

sudo update-grub

After a reboot memory.memsw.* settings are now available in cgroups

sample configuration for multiple process

Sample /etc/cgconfig.conf:

group chromium {
     # limit cpu to 2 cores : 2*100 percent *1000
     cpu {
         cpu.cfs_quota_us=200000;
     }
     # limit memory to 2 GB
     memory {
         memory.limit_in_bytes = 2048m;
         memory.memsw.limit_in_bytes = 2048m;
         memory.swappiness = 0;
     }
}

group firefox {
     # limit cpu to 4 cores : 4*100 percent *1000
     cpu {
         cpu.cfs_quota_us=400000;
     }
     # limit memory to 3 GB
     memory {
         memory.limit_in_bytes = 3072m;
         memory.memsw.limit_in_bytes = 3072m;
     }
}
group evolution {
     # limit cpu to 2 cores : 2*100 percent *1000
     cpu {
         cpu.cfs_quota_us=200000;
     }
     # limit memory to 1 GB
     memory {
         memory.limit_in_bytes = 1024m;
         memory.memsw.limit_in_bytes = 1024m;
     }
}
group rambox {
     # limit cpu to 2 cores : 2*100 percent *1000
     cpu {
         cpu.cfs_quota_us=200000;
     }
     # limit memory to 2 GB
     memory {
         memory.limit_in_bytes = 2048m;
         memory.memsw.limit_in_bytes = 2048m;
     }
}

group teams {
     # limit cpu to 2 cores : 2*100 percent *1000
     cpu {
         cpu.cfs_quota_us=200000;
     }
     # limit memory to 1.5 GB
     memory {
         memory.limit_in_bytes = 1536m;
         memory.memsw.limit_in_bytes = 1536m;
     }
}

Sample /etc/cgrules.conf:

#<user>                   <controllers>       <destination>
#<user>:<process name>    <controllers>       <destination>
dealingtrap:/snap/bin/chromium   cpu,memory        chromium
dealingtrap:chrome               cpu,memory        chromium
dealingtrap:/usr/bin/firefox     cpu,memory        firefox
dealingtrap:/usr/bin/evolution   cpu,memory        evolution
dealingtrap:/usr/libexec/evolution-data-server/evolution-alarm-notify  cpu,memory        evolution
dealingtrap:/usr/libexec/evolution-calendar-factory                    cpu,memory        evolution
dealingtrap:/usr/libexec/evolution-addressbook-factory                 cpu,memory        evolution
dealingtrap:/usr/libexec/evolution-source-registry                     cpu,memory        evolution
dealingtrap:/usr/bin/rambox      cpu,memory        rambox
dealingtrap:/opt/Rambox/rambox   cpu,memory        rambox
dealingtrap:/usr/bin/teams       cpu,memory        teams

Restart cg services to load the new configuration

systemctl restart cgconfigparser
systemctl restart cgrulesgend

Cgroups are applied at process creation, so be sure to restart the userspace process you want to see associated with a cgroup

alternatives

create systemd scopes from the command line

For launching a process as non-superuser with cpu, memory and I/O limits:

systemd-run --user --scope -p MemoryLimit=1G -p CPUShares=2048 -p BlockIOWeight=500 firefox

A scope is a systemd unit (a process container) that is not a service.

grouping systemd scopes into systemd slices

To allow user to create slices managing more than memory and pids (cpu and io, but ebpg and rdma cannot be delegated), edit the user service corresponding to you user uid with the following command:

sudo systemctl edit user@1000.service

and add the following content:

[Service]
Delegate=yes

Then, edit ~/.config/systemd/user/firefox.slice and add the following content:

[Slice]
MemoryAccounting=true
MemoryMax=256M
CPUAccounting=true
CPUQuota=25%

the slice ca now be used to contain scopes launch by the following command:

systemd-run --user --slice firefox --scope firefox

outside of userspace: systemd services

To control a systemd service here are some useful unit settings:

sudo systemctl edit foo.service --full

edit or add all or some of the following under the [Service] tag:

Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7
CPUQuota=200%
MemoryMax=1G
MemorySwapMax=0
IOWeight=20
CPUWeight=20

and restart the service:

sudo systemctl restart foo.service

as an exemple: /etc/systemd/system/eea.service:

[Unit]
Description=ESET Endpoint Antivirus
After=network.target

[Service]
Type=simple
ExecStartPre=/opt/eset/eea/lib/install_scripts/check_start.sh
ExecStart=/opt/eset/eea/sbin/startd
ExecStartPost=/bin/sleep 2
ExecStartPost=-/opt/eset/eea/lib/install_scripts/launch_gui_all_users.sh
ExecStopPost=-/usr/bin/killall /opt/eset/eea/lib/egui --quiet
KillMode=process
Restart=always
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7
CPUQuota=200%
MemoryMax=1G
MemorySwapMax=0
IOWeight=20
CPUWeight=20

[Install]
WantedBy=multi-user.target

Last modified: Sat Sep 13 01:55:42 2025